Продавцу нужен язык, покупателю — глаза.
Бенджамин Франклин
Создание и подготовка базы данных
Структура нашего Интернет-магазина
Главная страничка — выбор типа заказа (файл index.asp)
Список позиций заданной категории (List.asp)
Добавление в корзину и просмотр корзины AddToCart.asp и ShowCart.asp
Сбор данных о покупателе (файл EmailOrder.asp)
Oтправка заказа по e-mail (файл Done.asp)
Проверка пользовательского ввода
В частях 4 и 5 статьи «<% ASP на блюдечке %>» («Виртуальный магазин» и «Виртуальный магазин (продолжение)») читателю был предложен инструментарий, позволяющий создавать Интернет-магазины по принципу подбора составляющих (комплектующих, комплектаций, деталей, услуг и т.д.). Такой подход целесообразен во всех случаях, когда потенциального клиента интересуют возможные сочетания определенной совокупности товаров или услуг, причем с возможностью подбора подобной совокупности как самостоятельно, так и с помощью некоего «виртуального гида», интеллектуализации которого и была посвящена пятая часть статьи. И хотя такая постановка задачи охватывает достаточно широкий спектр Интернет-поставок товаров и услуг, все-таки сама концепция подбора вариантов в некотором смысле лишена универсальности. Здесь все зависит от целей, которые преследует та или иная компания, предлагающая свои товары или услуги с помощью Интернета.
В своих письмах читатели просят рассказать о реализации принципиально универсального, хотя и несколько старомодного подхода к построению Интернет-магазина. Этой теме и посвящена настоящая статья.
Концепция, изложенная в настоящей статье, хотя и несколько старомодна, однако с ее помощью можно реализовать всевозможные Интернет-магазины. Рассмотрим эту концепцию, а заодно представим реализуемую задачу поподробнее. Во-первых, это структурированная система предоставляемых товаров или услуг, реализованная в форме электронного каталога — как правило, линейной или древовидной структуры — в зависимости от степени сложности и детализованности того или иного магазина. Иными словами, это категории товаров, содержащие, в свою очередь, подкатегории и/или товары. Во-вторых, это механизм выбора определенного количества определенных товаров и их добавления в «корзину» (названную так по аналогии с обычным магазином). И наконец, в-третьих, это система регистрации заказа: отправка заказа по электронной почте, регистрация заказа в базе данных, оплата заказа по кредитной карточке и т.д. Совокупность трех этих компонентов и является по своей сути самым обычным и зачастую самым распространенным Интернет-магазином.
Существуют разнообразные вариации рассмотренной выше концепции Интернет-магазина, их огромное множество, но наиболее распространенными являются:
Известно, что из множества Интернет-магазинов особо выделяются, как правило, магазины компьютеров, бытовой техники, средств мобильной связи, медикаментов, а не продуктов питания, одежды и предметов первой необходимости. В любом случае, огромное внимание следует уделить представлению товара в Интернет-магазине, ведь покупка, к примеру, телевизора или монитора сводится не только к ознакомлению с его техническими характеристиками, но и к осмотру, «ощупыванию». Именно поэтому реализация некоторых Интернет-магазинов пока несколько затруднительна. Хотя в ряде случаев предпринимаются довольно удачные попытки воссоздания реального магазина, однако пока еще они очень далеки от совершенства.
Начнем с постановки задачи. При этом предполагается, что читатель знаком с основами ASP- и SQL-программирования — первых частей настоящей статьи для этого будет вполне достаточно.
По сути дела мы хотим организовать базу данных всего перечня товаров гипотетического магазина — магазина компьютеров и комплектующих, реализовать средства предъявления товаров, позволить покупателю выбирать и добавлять товары в корзину и посылать заказ по электронной почте.
Согласитесь, что предложенная задача весьма актуальна и на первый взгляд может показаться очень сложной, однако это не совсем так.
Для начала давайте представим себе, в чем состоит процесс покупки комплектующих, и попытаемся формализовать его. Этот процесс описывается последовательностью следующих шагов:
Как видите, последовательность выполняемых шагов по взаимодействию клиента с системой крайне проста, так что теперь можно переходить к проектированию базы данных.
Для создания базы данных (назовем ее Ishop) нам понадобится Microsoft SQL Server 7.0 или 2000. От процесса проектирования базы данных будет зависеть дальнейший объем программной логики нашего приложения, поэтому данный этап крайне ответственен. Советуем вам при проектировании Интернет-магазина стремиться к тому, чтобы ваши странички содержали как можно меньше строк и констант. Выведите все, что можно, за их пределы, вплоть до наименований позиций, так как последние могут меняться довольно часто. Иначе говоря, добейтесь, чтобы ваш код был универсальным и независимым от данных. Но поскольку принципы проектирования баз данных выходят за рамки настоящей статьи, не будем на них задерживаться и представим структуру нашей базы данных следующим образом. Создадим одну управляющую таблицу для хранения информации о наименованиях всех категорий и их соответствия таблицам с позициями, ценами и условиями гарантий (таблицу _Components), а также таблицы с перечнями позиций товаров заданных категорий.
Все таблицы создадим по одному и тому же шаблону с наименованием позиции (поле Title), розничной ценой (поле Price 1), мелкооптовой ценой (поле Price 2) и крупнооптовой ценой (поле Price 3), а также с условиями гарантии на товар (поле Description).
Далее необходимо прописать нашу базу данных в соответствующем разделе источников данных системы. Для этого сделайте следующее.
Теперь, когда база данных готова, можно приступать к созданию самого Интернет-магазина.
Для того чтобы было легче понять дальнейшее изложение, представим структуру нашего будущего Интернет-магазина, причем формы и действия при выборе конфигурации компьютера автоматически мы покажем синим цветом, при выборе конфигурации самостоятельно — зеленым, при выборе дополнительного оборудования — сиреневым, а начало и конец алгоритма-схемы — красным:
В предыдущих частях настоящей статьи были рассмотрены две первые ветви алгоритма-схемы. Теперь же рассмотрим подмножество алгоритма схемы, ограниченное пунктирной линией и помеченное значком «X». Как видно из схемы, в этом случае загружается набор из двух фреймов, расположенных вертикально (файл EquipFrameSet.html), причем левый фрейм загружает файл Equip.asp, а правый (основной) — файл List.asp. Затем, в зависимости от действий пользователя, производится либо добавление товаров в корзину (файл AddToCart.asp), либо просмотр корзины (файл ShowCart.asp), в любом случае ход дальнейшего «развития событий» одинаков: производится сбор информации о покупателе и отправка заказа по электронной почте.
Итак, уяснив структуру проектируемого приложения, мы можем приступить к написанию кода.
Для начала создадим страничку, в которой пользователь сможет выбрать один из трех режимов дальнейшего взаимодействия с сайтом — покупку компьютера с помощью эксперта, самостоятельно или покупку дополнительного оборудования:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>виртуальный магазин</title> </head> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> <table width="780" border="0" cellspacing="0" cellpadding="0"> <tr><td> <div align="center"> <p>Добро пожаловать в наш виртуальный магазин</p> <p><a href="auto.asp">Подбор компьютера автоматически (с нашей помощью)</a></p> <p><a href="MainForm.asp?ID=2">Подбор компьютера самостоятельно</a></p> <p><a href="equipframeset.html">Покупка комплектующих</a></p> </div> </td></tr></table> </body> </html>
Как видите, пока все просто, и параметр ID, равный 2, передается в форму MainForm.asp, где будет свидетельствовать о том, что пользователь пожелал выбрать состав компьютера самостоятельно.
Далее, как уже было отмечено, мы будем рассматривать именно эту ветвь, то есть не случай подбора комплектующих, а случай их независимой покупки. Организуем набор фреймов для отображения перечня категорий и для организации просмотра позиций текущей категории (для простоты в настоящей статье предполагается отсутствие вложенных категорий):
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Виртуальный магазин</title> </head> <frameset cols="200,*" frameborder="NO" border="0" framespacing="0"> <frame name="leftFrame" scrolling="YES" noresize src="Equip.asp"> <frame name="MainShopFrame" src="List.asp"> </frameset> <noframes> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> </body> </noframes> </html>
Теперь рассмотрим файл левого фрейма, содержащий список наименований категорий товаров. По сути, это набор ссылок на основной (правый) фрейм, причем организованный таким образом, что в качестве текстов самих ссылок используется наименование категории, а в качестве параметра в файл правого фрейма передается имя соответствующей таблицы базы данных. Для реализации вышеизложенного используется управляющая таблица Components:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Виртуальный магазин</title> </head> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> <table width="780" border="0" cellspacing="0" cellpadding="0"> <tr><td> <div align="center"> <div align="left"> <p><b>Комплектующие</b></p> <% Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop" SQLQuery = "Select * From _Components ORDER BY CategoryName ASC" Set rs = db.Execute(SQLQuery) Do While NOT rs.EOF CurrentCategory = CurrentCategory + 1 CurTableName = rs.Fields("CategoryTableName").value CategoryName = rs.Fields("CategoryName").value Response.Write "<a href='List.asp?TName=" & CurTableName &_ "' class='antiLine' target='MainShopFrame'>" & CategoryName & "</a><br>" rs.MoveNext Loop db.Close Set db = Nothing %> </div> </td></tr></table></div> </body> </html>
Как видите, производится подключение к базе данных и выполняется выборка из таблицы _Components. Затем в цикле динамически формируются ссылки на файл List.asp с параметрами, которые в дальнейшем будут использованы для построения запроса к необходимой таблице данных - в зависимости от категории товаров, выбираемой пользователем при переходе по соответствующей ссылке.
Теперь надлежит организовать просмотр списка позиций товаров заданной категории и предоставить пользователю механизм добавления в корзину заданного количества единиц товара. Здесь прежде всего необходимо уяснить для себя понятие «корзина» и уточнить порядок взаимодействия с ней.
Итак, с точки зрения пользователей корзина должна представлять собой окно с перечнем добавленных товаров или услуг, с указанием их цены и добавленного количества. В некоторых случаях необходима и возможность редактирования этого перечня. С точки же зрения разработчиков, то есть нас с вами, корзина - это определенная область памяти, в которой должна храниться информация о сделанных заказах, причем эта область памяти - сессионная, то есть обнуляется при открытии новой сессии.
Вообще говоря, возможны два подхода к созданию корзины: с использованием сессионных переменных и с использованием «ключиков» (cookies). Каждый из этих механизмов имеет свои преимущества и недостатки. Так, достоинство первого механизма заключается в большей гибкости (большем числе возможностей) и большей защищенности (сессионные переменные недоступны для клиента), а второй механизм, в отличие от первого, хранит информацию в браузере клиента, что разгружает канал передачи данных от сервера к клиенту.
В нашем случае мы используем механизм сессионных переменных, то есть в качестве области хранения информации о заказе будут использоваться переменные, принадлежащие сессии нашего Web-приложения:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Виртуальный магазин</title> </head> ' Сформируем ссылку на файл, организующий показ корзины, и будем передавать ' в него параметр, определяющий сбрасывание содержимого корзины. <a href="javascript:op('ShowCart.asp?Clear=1')">Ваша корзина</a> <% CartItems = Session ("CartItems") ' Прочитаем количество пунктов, добавленных в корзину из сессионной переменной CartItems Height = CInt(CartItems) * 20 + 150 ' Вычислим высоту генерируемого окна корзины и установим ограничение на ее значение If (Height >= 600) Then Height = 600 End if If (CartItems = 0) Then Response. Write "Ваша корзина пуста." Else Response.Write "Всего в корзине " & CartItems If (CartItems = 1) Then Response. Write " позиция" End If If (CartItems = 2 OR CartItems = 3 OR CartItems = 4) Then Response. Write " позиции" End If If (CartItems >= 5) Then Response. Write " позиций" End If End If %> <Script> <% ' Генерация JavaScript функции показа корзины (передаем в качестве параметра высоту окна) Response.Write "function op(URL)" Response.Write "{var wnd=open(URL,'','resizable=1,toolbar=0,directories=0,statusbar=0,width=720,height=" Response.Write CStr(Height) & "');}" %> </Script> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> <form method="get" name= "MainForm" action="AddToCart.asp"> <table width="780" border="0" cellspacing="0" cellpadding="0"> <tr><td> <div align="left"> <table width="620" border="2" cellspacing="0" cellpadding="0"> <tr> <td width="465"><b><center>Позиция</center></b></td> <td width="16"><b><center>Цена</b></center></td> <td width="46"><b><center>Кол-во</b></center></td> <td width="20"><b><center>+</b></center></td> </tr> <% ' Прочитаем имя таблицы данных из предыдущей формы ' и обновим значение соответствующей сессионной переменной TableName = Request.QueryString("TName") Session ("TName") = TableName 'Осуществим подключение к базе данных и выполним запрос к указанной таблице данных Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop" ' Если имя таблицы не пусто, организуем цикл показа позиций If TableName <> "" Then SQLQuery = "Select * From " & TableName & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC" Set rs = db.Execute(SQLQuery) CurrentCategory = 1 Do While NOT rs.EOF Response.Write "<tr><td>" & rs.Fields("Title").value & "</td>" Response.Write "<input type='hidden' name='Title" & CurrentCategory & _ "' value='" & rs.Fields("Title").value & "'>" Response.Write "<td>" & rs.Fields("Price1").value & "</td><td>" 'Определим текстовое поле для ввода значений количества единиц товара ' и кнопку, осуществляющую добавление товаров в корзину (переход к следующей форме) Response.Write "<input id = 'quantity'" & CurrentCategory & " type='text' name='quant" &_ CurrentCategory & "' maxlength='5' size='5'>" Response.Write "</td><td>" Response.Write "<INPUT type='submit' value='+' name=submit></td></tr>" rs.MoveNext CurrentCategory = CurrentCategory + 1 Loop Response.Write "</table><br>" db.Close Set db = Nothing Else End If %> <br> </form> </body> </html>
Обратите внимание на то, что в цикле по результатам выполнения выборки всех записей таблицы заданной категории, по сути, выполняется генерация кнопок типа Submit, выполняющих загрузку странички-действия (указанной атрибутом action формы), в данном случае - странички добавления позиции в корзину AddToCart.asp.
Как было сказано выше, при добавлении позиций в корзину (при нажатии на кнопку «+») производится передача управления файлу AddToCart.asp:
<head> <title>Ваша корзина</title> </head> <% ClearAll = 0 'Организация опроса кнопок корзины CurAction = Request.QueryString("Submit") If (CurAction = "Очистить корзину") Then Session ("Cart") = "" Session ("CartItems") = 0 Session ("Sum") = 0 ClearAll = 1 End If If (CurAction = "Оформить заказ") Then Response.Redirect "EmailOrder.asp?IsCart=1" End If ' Считывание сессионной переменной с именем таблицы данных TableName = Session("TName") ' Организация подключения к базе данных и выборка значений Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop" If TableName <> "" Then SQLQuery = "Select * From " & TableName & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC" Set rs = db.Execute(SQLQuery) CurrentCategory = 1 CurCart = "" Sum = Session ("Sum") CartItems = CInt(Session ("CartItems")) If (ClearAll <> 1) Then ' Формирование строки с компонентами корзины для тех записей таблицы, ' соответствующие которым значения количества товара не равны 0 Do While NOT rs.EOF Str = "quant" & CStr(CurrentCategory) CurQuant = Request.QueryString(Str) If Not IsNumeric(CurQuant) Then Response.Write "Ошибка указания единиц позиции." Else If (CurQuant <> "0" AND CurQuant <> "") Then CurCart = "<tr><td>" & rs.Fields("Title").value & "</td>" CurCart = CurCart & "<td>" & rs.Fields("Price1").value & "</td><td>" CurCart = CurCart & CStr(CurQuant) & "</td><td>" Total = CInt(CurQuant) * rs.Fields("Price1").value Sum = Sum + Total CurCart = CurCart & CStr(Total) & "</td></tr>" CartItems = CartItems + 1 End If End If rs.MoveNext CurrentCategory = CurrentCategory + 1 Loop ' Обновление сессионных переменных ' CartItems – количество элементов корзины ' CartVal – HTML-представление элементов корзины, то есть значение корзины ' Sum – итоговая сумма цен элементов корзины Session ("CartItems") = CartItems CartVal = Session ("Cart") Session ("Cart") = CartVal & CurCart CartVal = Session ("Cart") Session ("Sum") = Sum End IF End If db.Close Set db = Nothing Response.Redirect "List.asp?TName=" & Session ("TName") ' Безусловный переход к файлу List.asp с параметром (именем таблицы данных) %>
Следует обратить особое внимание на последнюю строку:
Response.Redirect "List.asp?TName=" & Session ("TName")
По сути, осуществляется не переход, а возврат к страничке List.asp. Если же принять во внимание то обстоятельство, что текущая страничка (AddToCart.asp) никаких видимых (заметных для пользователя) действий (кроме добавления позиций в соответствующую сессионную переменную) не производит, то с точки зрения пользователя ровным счетом ничего не происходит.
Обратите внимание также и на то, каким образом производится обработка нажатий на кнопки «Очистить корзину» и «Оформить заказ». Будучи кнопками типа submit-формы, реализованной на страничке ShowCart.asp (см. об этом ниже), они возвращают определенные значения (которые мы зададим впоследствии), что мы и используем для обнуления корзины (сессионных переменных, хранящих содержимое корзины) и оформления заказа (безусловной передачи управления страничке EmailOrder.asp).
Как видите, сама сессионная переменная, содержащая добавленные в корзину позиции, представляет собой простую совокупность последовательно прибавляемых строк с необходимыми данными, заключенными в тэги таблицы. Конечно, это далеко не самый лучший способ организации хранения данных в корзине (в частности, он не позволяет осуществлять редактирование ее содержимого), но тем не менее в определенных случаях разработчики довольствуются и им.
Файл ShowCart.asp отличается от файла AddToCart.asp лишь тем, что вместо осуществления конкатенации (добавления) к сессионной переменной содержимого корзины, он попросто организует показ этого содержимого в новом окне:
… Do While NOT rs.EOF Str = "quant" & CStr(CurrentCategory) CurQuant = Request.QueryString(Str) If (CurQuant <> "0" AND CurQuant <> "") Then CurCart = "<tr><td>" & rs.Fields("Title").value & "</td>" CurCart = CurCart & "<td>" & rs.Fields("Price1").value & "</td><td>" CurCart = CurCart & CStr(CurQuant) & "</td><td>" Total = CInt(CurQuant) * rs.Fields("Price1").value Sum = Sum + Total CurCart = CurCart & CStr(Total) & "</td></tr>" End If rs.MoveNext CurrentCategory = CurrentCategory + 1 Loop CartVal = Session ("Cart") Session ("Cart") = CartVal & CurCart CartVal = Session ("Cart") Session ("Sum") = Sum Response.Write CartVal …
Последняя строка приведенного фрагмента исходного текста и осуществляет вывод содержимого корзины на экран.
В результате получится система, состоящая из списка категорий, списка позиций выбранной категории и корзины (см. рисунок).
Далее следует обычная страничка сбора информации о пользователе:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> </head> <body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00"> <div align="center"> <p>Отправка заказа по электронной почте:</p> <p>Как с Вами связаться</p> <Form Method="get" Action = "Done.asp"> <table> <tr> <td>Ваше имя:</td> <td><Input Type="text" Name="Name" Size="30"></Input></td> </tr> <tr> <td>Ваш телефон:</td> <td><Input Type="text" Name="Phone" Size="30"></Input></td> </tr> <tr> <td>Ваш адрес:</td> <td><Input Type="text" Name="Address" Size="30"></Input></td> </tr> <tr> <td>Ваш электронный адрес:</td> <td><Input Type="text" Name="Email" Size="30"></Input></td> </tr> <tr> <td>Ваш UIN:</td> <td><Input Type="text" Name="UIN" Size="30"></Input></td> </tr> <tr> <td align = center><Input Type="submit" Value="Отправить заказ"></Input></td> </tr> </table> <% I = 1 Do While I <= 15 ' Прочитаем в цикле значения скрытых полей «select#» ' и сгенерируем скрытые элементы формы ' для передачи выбранных значений в последующие скрипты Str = "select" Str = Str & CStr(I) Res = Request.QueryString(Str) Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>" ' Прочитаем в цикле значения скрытых полей «quant#» ' и сгенерируем скрытые элементы формы ' для передачи выбранных значений в последующие скрипты Str = " quant" Str = Str & CStr(I) Res = Request.QueryString(Str) Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>" ' Прочитаем в цикле значения скрытых полей «price#» ' и сгенерируем скрытые элементы формы ' для передачи выбранных значений в последующие скрипты Str = "price" Str = Str & CStr(I) Res = Request.QueryString(Str) Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>" I = I + 1 Loop ' Если на страничку пришли из корзины, то заведем скрытое поле ' и придадим ему соответствующее значение If (Request.QueryString("IsCart") = 1) Then Response.Write "<input type='hidden' name='Cart' value='1'>" End If %> </Form> <br> </div> </body> </html>
После того как все действия выполнены успешно, необходимо сформировать электронное письмо, которое одновременно должно быть послано как гипотетическому менеджеру по продажам или доставке нашего виртуального магазина, так и самому пользователю в подтверждение выполненного заказа. Для этого воспользуемся стандартной ActiveX компонентой CDONTS:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Виртуальный магазин</title> </head> <body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00"> <table width="780" border="0" cellspacing="0" cellpadding="0"> <tr><td> <div align="center"> <% Name = Request.QueryString("Name") Phone = Request.QueryString("Phone") Address = Request.QueryString("Address") Email = Request.QueryString("Email") UIN = Request.QueryString("UIN") Dim myMail Set myMail = CreateObject("CDONTS.NewMail") myMail.From = Email myMail.To = "rouben@iname.com" myMail.Subject = "Order from" & Name Body = Body & "Уважаемый " & Name & "!" & CHR(13) & CHR(10) Body = Body & "Имя: " & Name & CHR(13) & CHR(10) Body = Body & "Телефон: " & Phone & CHR(13) & CHR(10) Body = Body & "Адрес: " & Address & CHR(13) & CHR(10) Body = Body & "E-mail: " & Email & CHR(13) & CHR(10) Body = Body & "UIN: " & UIN & CHR(13) & CHR(10) & CHR(13) & CHR(10) Body = Body & "Вы заказали:" I = 1 Total = CDbl(0) ComponentCount = Session("ComponentCount") 'Если это не корзина, то будем осуществлять обработку обычным способом If (Request.QueryString ("Cart") <> 1) Then Do While I <= ComponentCount Body = Body & CHR(13) & CHR(10) & I & ". " Str = "select" Str = Str & CStr(I) Res = Request.QueryString(Str) Body = Body & " - " & Res & " - " Str = "quant" Str = Str & CStr(I) Res1 = Request.QueryString(Str) Body = Body & Res1 & " - " I = I + 1 Loop ' В противном случае произведем добавление к телу электронного письма ' сессионной переменной с содержимым корзины Else CartVal = Session ("Cart") Body = Body & CartVal End If D = Date() D = FormatDateTime(D,1) Body = Body & CHR(13) & CHR(10) Body = Body & "Отправленно:" & D Body = Body & CHR(13) & CHR(10) Body = Body & "Итого с Вас: " & Total & " у.е." & CHR(13) & CHR(10) & CHR(13) & CHR(10) Body = Body & "Наши менеджеры свяжутся с Вами в ближайшее время по оставленным Вами координатам." Body = Body & CHR(13) & CHR(10) & "С наилучшими пожеланиями" & CHR(13) & CHR(10) Body = Body & "Сервер 'Виртуального магазина'" myMail.Body = Body 'Response.Write Body On Error Resume Next myMail.Send If Err <> 0 Then Response.Write "Error encountered: " & Err.Description End If Response.Write "<center><p>Уважаемый " & Name & "!<br>" Response.Write "Ваш заказ был успешно отправлен на сервер Виртуального магазина.<br>" Response.Write "Спасибо!</p></center>" %> </div> </td></tr></table> </body> </html>
Разумеется, ни один мало-мальски солидный Интернет-магазин не обходится без такого важного инструментария, как поиск позиций. Здесь возникает целая куча вопросов о том, что, где, как и по каким критериям искать. Скажем сразу, что однозначно ответить на все эти вопросы невозможно, поскольку это зависит от специфики поставляемых товаров или услуг и «заточено» под конкретные коммерческие цели, преследуемые теми или иными организаторами Интернет-торговли. Однако осмелимся предложить возможное решение, основанное с инструментальной точки зрения на результатах просмотра многочисленных Интернет-магазинов самого широкого спектра товаров. Для простоты дальнейшего изложения рассмотрим пример, связанный с нашим магазином.
Прежде всего необходимо организовать форму поиска по ключевым словам (по подстроке) в наименованиях позиций, причем как по всем категориям (по всей базе данных), так и по заданной (следовательно, нужно предусмотреть компонент выбора категории поиска). Кроме того, стоит предусмотреть возможность поиска товаров и по ценовым критериям, например искать все товары, цена которых меньше определенного заданного значения. Совокупность этих критериев и будет определять результаты поиска. Итак, для начала создадим форму поиска, удовлетворяющую описанным выше критериям (см. рисунок):
Как видите, форма попросту добавлена в файл страницы списка позиций заданной категории List.asp. Сделано это простым добавлением строки в начало файла List.asp:
<!--#include file="SearchForm.asp" -->
Сама же форма (как явствует из ссылки на соответствующий файл) представлена в файле SearchForm.asp следующим образом:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Виртуальный магазин</title> </head> <body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00"> <% Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=ISHop; UID=sa;PWD=;database= ISHop" SQLQuery = "SELECT * FROM _Components ORDER BY CategoryName ASC" Set rs = db.Execute(SQLQuery) %> <form name="SearchForm" method="get" action="Search.asp"> <p> Искать: <input type="text" name="SearchString" size="15" maxlength="15"> в категории: <select style="WIDTH: 140px" name="CategorySel"> <option value="AllCategories">Во всех</option> <% Do While NOT rs.EOF Response.Write "<option value='" & rs.Fields("CategoryTableName").value & _ "'>" & rs.Fields("CategoryName").value & "</option>" rs.MoveNext Loop %> </select> цена: <select name="BounderSel"> <option value="AnyPrice"></option> <option value="<="><=</option> <option value=">=">>=</option> </select> <input type="text" name="PriceBound" size="3" maxlength="4"> <input type="submit" name="Submit" value="Поиск"> </p> </form> <% db.Close Set db = Nothing %> </body> </html>
Здесь в качестве обработчика формы указана страничка Search.asp, по сути являющаяся модификацией файла List.asp для случая формирования списка позиций не из одной, а из нескольких таблиц, согласно введенным критериям запроса. Приведем фрагмент кода странички Search.asp, отвечающий за формирование запросов к базе данных, исходя из состояния полей нашей поисковой формы:
<% … SearchString = Request.QueryString("SearchString") CategorySel = Request.QueryString("CategorySel") BounderSel = Request.QueryString("BounderSel") PriceBound = Request.QueryString("PriceBound") … If SearchString = "" Then If (BounderSel = "AnyPrice" OR PriceBound = "" ) Then SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC" Else SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'" &_ " AND Price1 " & BounderSel & PriceBound & " ORDER BY Title ASC" End If Else If (BounderSel = "AnyPrice" OR PriceBound = "" ) Then SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'" &_ " AND Title LIKE '%" & SearchString & "%' ORDER BY Title ASC" Else SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'” &_ ” AND Title LIKE '%" & SearchString & _ "%' AND Price1 " & BounderSel & PriceBound & " ORDER BY Title ASC" End If End If … %>
Как видите, после считывания значений полей нашего поискового компонента в переменные, производится анализ пользовательского ввода и формируется строка запроса к базе данных исходя из введенных значений.
Единственным существенным отличием от файла и странички List.asp является то, что поиск может быть осуществлен по всем таблицам данных, для этого:
<% … 'Если пользователь запустил поиск по всем категориям, т.е. таблицам If (CategorySel = "AllCategories") Then SQLQuery = "Select * From _Components" Set res = db.Execute(SQLQuery) Do While NOT res.EOF CurTableName = res.Fields("CategoryTableName").value 'Функция показа содержимого текущей таблицы FetchFromTable CurTableName res.MoveNext Loop 'В противном случае (поиск только по одной таблице) Else FetchFromTable CategorySel End If … %>
Таким образом, сделав несколько изменений и слегка переработав страничку показа списка позиций заданной категории List.asp, можно получить страничку вывода результатов поиска Search.asp (предлагаем вам проделать это самостоятельно).
В завершение хотелось бы рассмотреть несколько полезных JavaScript-сценариев для проверки корректности ввода информации о пользователе и всевозможных типов данных. В связи с тем, что наблюдается определенный дефицит таких функций, была разработана библиотека сценариев, использование которых позволило облегчить задачу обработки пользовательского ввода. Для удобства все функции сгруппированы в один файл (script.js):
… Проверка целого значения … function isInteger (s,message){ // s is a string // message – строка с сообщением об ошибке var i; for (i = 0; i < s.length; i++){ // Убедимся, что текущий символ является цифрой var c = s.charAt(i); if (!isDigit(c)) { alert(message); return false; } } return true; } … Проверка цифры … function isDigit (c) { // c – символ return ((c >= "0") && (c <= "9")) } … Преобразование строки в число с отбрасыванием посторонних символов … function numericize(s) { // s – строка // message – строка с сообщением об ошибке var i,j; j=""; for (i=0;i<s.length;i++) { if (isDigit(s.charAt(i))){ j=j+s.charAt(i); } } return j; } … Проверка «пустоты» введенного значения … function isBlank (s,message) { // s – рассматриваемый элемент формы // message – строка с сообщением об ошибке if ((s.value.length > 0) && (s.value != null) && (s.value != "")){ return false; } alert(message); s.focus(); return true; } … Проверка номера телефона … function isPhone (s,message) { // s – рассматриваемый элемент формы // message – строка с сообщением об ошибке // Удалим символы, не являющиеся цифрами, и вычислим длину полученной строки if (s.value.length > 10) { s.value = numericize(s.value); } //По крайней мере 3 цифры – код города и 7 цифр — номер телефона if (s.value.length == 10) { if (isInteger(s.value,message)) { return true; } else { s.focus(); return false; } } else { alert(message); s.focus(); return false; } return true; } … Проверка адреса электронной почты … function isEmail (s,message) { // s – рассматриваемый элемент формы // message – строка с сообщением об ошибке var i,ii; var j; var k,kk; var jj; var len; // Пусто? if (isBlank(s,message)) { s.focus(); return false; } // Проверка адреса электронной почты // Адрес должен содержать "@" и "." // В строке адреса должен быть хотя бы 1 символ до символа "@" // После символа "@" и перед символом "." должен быть хотя бы 1 символ // после символа "." должно быть по крайней мере еще 2 символа if (s.value.length >0) { i =s.value.indexOf ("@"); ii=s.value.indexOf ("@",i+1); j=s.value.indexOf (".",i); k=s.value.indexOf (","); kk=s.value.indexOf (" "); jj=s.value.lastIndexOf (".")+1; len=s.value.length; if ((i>0) && (j>(1+1)) && (k==-1) && (ii==-1) && (kk==-1) && (len-jj >=2) && (len-jj<=3)) {} else { alert(message) s.focus(); return false; } } return true; } … Проверка выбора значения из списка … function isSelected (s,message) { // s – рассматриваемый элемент формы // message – строка с сообщением об ошибке // Проверяет список выбора на предмет изменения его значения // по сравнению со значением, задаваемым по умолчанию if (s.selectedIndex==0) { alert(message); s.focus(); return false; } return true; }
Использовать данный файл крайне просто. Для этого в тэге объявления формы в качестве скрипта проверки необходимо указать определенную функцию, например:
… <Form Name="MainForm" ACTION="Process.asp" Method=Post onSubmit="return PreProcess();"> …
Далее следует включить вышеприведенный файл с библиотекой функций в разрабатываемое Web-приложение:
… <Script Type = "text/javascript" Src = "script.js"> <!-- // В случае, если библиотека не найдена document.write ("Библиотека JavaScript не найдена."); //--> </Script> …
Определить функцию проверки, которая и будет осуществлять вызов необходимых функций нашей библиотеки:
<Script Tupe = "text/javascript"> function PreProcess() { var ok; with (document.MainForm) { // Пусто ли имя if (isBlank(name,'Введите имя.')) { return false; } // Проверка номера домашнего телефона if (!isPhone (homephone,'Введите корректный номер домашнего телефона.')) { return false; } // Проверка адреса электронной почты if (!isEmail (email,'Пожалуйста, введите корректный адрес электронной почты.')) { return false; } } return true; } </Script>
Как уже неоднократно было сказано выше, Интернет-магазинов великое множество. И если раньше они считались всего лишь игрушками, не позволяющими реально осуществлять ежедневные покупки всевозможных товаров, то теперь это серьезные системы, за которыми стоят не менее серьезные организации, профессионально занимающиеся бизнесом. В последнее время понятие Интернет-торговли перестало быть чем-то экзотическим, а возможность приобрести практически любой товар, не вставая из-за компьютера, стала поистине огромной.
Прежде чем приступать к созданию своего Интернет-магазина, советуем для начала «побродить»по чужим. Для ориентации читателей в мире отечественных Интернет-магазинов приведем список наиболее привлекательных из них:
MEGAShop - магазин компьютерной техники http://www.megashop.ru/index14.html
Kenga - магазин детских товаров и игрушек http://www.kenga.ru/toys_main.php3
24x7 - книги, видео, музыка, игрушки http://www.24x7.ru/
Каталог книжных магазинов зоны .ru http://www.findbook.h1.ru/
Korzina.ru - российская сеть магазинов с доставкой http://www.korzina.ru/
WebMarket.ru - http://www.webmarket.ru/
Торговый город - http://www.delo.omsknet.ru/shop/
Электронный торговый дом AVT - http://www.avt.ru/etd.shtml/
Полный архив исходных текстов ASP-страниц к настоящей статье лежит здесь.
КомпьютерПресс 4'2001